/**
 * @file store.c
 * @brief
 *
 * @author morris (a_morris@163.com)
 * @version v0.0.1
 * @date
 *
 *
 * @htmlonly <span style="font-weight: bold">History</span> @endhtmlonly
 *
 * Version|Describe|Auther|Date|comment
 * ------|------|------|------|------
 *
 *
 * @copyright <h2><center>Copyright &copy; 2024 All Rights Reserved.</center></h2>
 */
#include "store.h"

#include <stdint.h>

#include "acommon_err.h"
#include "bsp.h"
#include "eeprom.h"
#include "store_partition_eeprom.h"

#define STORE_CLRBIT(var, bit) (var &= (~(0x01 << bit)))

typedef struct
{
    uint8_t  flag;
    uint16_t front;
    uint16_t rear;
} store_record_head_t;
static store_record_head_t s_store_record_head = {0};

acommon_err_t store_event_record_load(void)
{
    acommon_err_t ret = eeprom_read_buff(STORE_RECORD_HEAD_ADDRESS_BASE, (uint8_t *) &s_store_record_head,
                                         sizeof(store_record_head_t));

    ACOMMON_LOGV(
        "record %d/%d, size: %d", s_store_record_head.front, s_store_record_head.rear,
        ((s_store_record_head.rear - s_store_record_head.front + STORE_RECORD_NUMBER_MAX) % STORE_RECORD_NUMBER_MAX));

    if (s_store_record_head.flag != 0x55)
    {
        memset((void *) &s_store_record_head, 0, sizeof(store_record_head_t));
        s_store_record_head.flag = 0x55;
        ret                      = eeprom_write_buff(STORE_RECORD_HEAD_ADDRESS_BASE, (uint8_t *) &s_store_record_head,
                                                     sizeof(store_record_head_t));

        ACOMMON_LOGD("record reset %d/%d", s_store_record_head.front, s_store_record_head.rear);
    }
    return ret;
}

acommon_err_t store_event_record_write(const bk9000_event_record_t *record)
{
    acommon_err_t ret = ACOMMON_OK;
    uint16_t      address;
    s_store_record_head.rear = (s_store_record_head.rear + 1) % STORE_RECORD_NUMBER_MAX;
    if (s_store_record_head.front == s_store_record_head.rear)
        s_store_record_head.front = (s_store_record_head.front + 1) % STORE_RECORD_NUMBER_MAX;

    ret = eeprom_write_buff(STORE_RECORD_HEAD_ADDRESS_BASE, (uint8_t *) &s_store_record_head,
                            sizeof(store_record_head_t));
    ACOMMON_LOGD("write record info %d/%d", s_store_record_head.front, s_store_record_head.rear);
    if (ret == ACOMMON_OK)
    {
        address = STORE_RECORD_DATA_ADDRESS_BASE + (s_store_record_head.rear * sizeof(bk9000_event_record_t));
        ret     = eeprom_write_buff(address, (uint8_t *) record, sizeof(bk9000_event_record_t));

        ACOMMON_LOGD("write record[%02X] %d", address, ret);
    }

    return ret;
}

acommon_err_t store_event_record_read(uint8_t idx, bk9000_event_record_t *record)
{
    acommon_err_t ret  = ACOMMON_OK;

    uint16_t address   = (s_store_record_head.front + idx) % STORE_RECORD_NUMBER_MAX;
    address           *= sizeof(bk9000_event_record_t);
    address           += STORE_RECORD_DATA_ADDRESS_BASE;

    ret                = eeprom_read_buff(address, (uint8_t *) record, sizeof(bk9000_event_record_t));

    return ret;
}

acommon_err_t store_operation_load(bk9000_unit_operation_t *data)
{
    return eeprom_read_buff(STORE_OPERATION_ADDRESS_BASE, (uint8_t *) data, sizeof(bk9000_unit_operation_t));
}

acommon_err_t store_operation_save(bk9000_unit_operation_t data)
{
    return eeprom_write_buff(STORE_OPERATION_ADDRESS_BASE, (uint8_t *) &data, sizeof(bk9000_unit_operation_t));
}

acommon_err_t store_unit_info_get(bk9000_unit_info_t *info)
{
    return eeprom_read_buff(STORE_INFO_ADDRESS_BASE, (uint8_t *) info, sizeof(bk9000_unit_info_t));
}

acommon_err_t store_unit_info_save(bk9000_unit_info_t info)
{
    //  s_store_info.address = 0;
    return eeprom_write_buff(STORE_INFO_ADDRESS_BASE, (uint8_t *) &info, sizeof(bk9000_unit_info_t));
}

acommon_err_t store_unit_info_memset_default(bk9000_unit_info_t *info)
{
    acommon_err_t ret = ACOMMON_OK;

    memset((void *) &info->ZM, 0xff, sizeof(info->ZM));
    info->address = 0;
    info->type    = bps_get_device_type();
    info->trunk   = 0;
    info->branch  = 0;

    return ret;
}

acommon_err_t store_unit_info_reset(bk9000_unit_info_t *info)
{
    acommon_err_t ret = ACOMMON_OK;

    store_unit_info_memset_default(info);

    ret = eeprom_write_buff(STORE_INFO_ADDRESS_BASE, (uint8_t *) info, sizeof(bk9000_unit_info_t));

    memset((void *) &s_store_record_head, 0, sizeof(store_record_head_t));
    s_store_record_head.flag = 0x55;
    ret                      = eeprom_write_buff(STORE_RECORD_HEAD_ADDRESS_BASE, (uint8_t *) &s_store_record_head,
                                                 sizeof(store_record_head_t));

    return ret;
}

int store_sn_check(const bk9000_unit_info_t *info, const uint8_t *const sn)
{
    int res = (1 << 6) - 1;
#if 0

    for (int i = 0; i < 6; i++)
    {
        if (info->sn[i] != 0x0 && info->sn[i] != 0xff && sn[i] == info->sn[i]) { STORE_CLRBIT(res, i); }
    }
#endif
    for (int i = 0; i < 6; i++)
    {
        if (info->sn[i] != sn[i])
        {
            eeprom_write_buff(STORE_INFO_ADDRESS_BASE, (uint8_t *) sn, 6);
            bsp_delay_ms(10);
			break;
        }
        STORE_CLRBIT(res, i);
    }

    return (res & 0x3f) ? 1 : 0;
}
